package com.example.g5project.chat.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.g5project.chat.mapper.ChatMapper;
import com.example.g5project.chat.model.dto.ChatDTO;
import com.example.g5project.chat.model.param.AppraiseParam;
import com.example.g5project.chat.model.param.ChatRecordListQueryParam;
import com.example.g5project.chat.model.param.CreateChatParam;
import com.example.g5project.chat.model.param.FinishChatParam;
import com.example.g5project.chat.model.param.InputingStatusParam;
import com.example.g5project.chat.model.po.ChatPO;
import com.example.g5project.chat.service.ChatService;
import com.example.g5project.chat.util.IMUserIdUtils;
import com.example.g5project.chat.util.RedisServiceUtils;
import com.example.g5project.customer.model.po.BasePO;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ChatServiceImpl extends ServiceImpl<ChatMapper, ChatPO> implements ChatService {

    @Autowired
    private IMUserIdUtils imUserIdUtils;
    @Autowired
    private RedisServiceUtils redisServiceUtils;

    /**
     * 获取设置时redis key
     *
     * @param param
     * @return
     */
    private String getSetInputingRedisKey(InputingStatusParam param) {
        String imMyId = imUserIdUtils.getIMUserId(param.getMe());
        String imOtherId = imUserIdUtils.getIMUserId(param.getOther());
        return imMyId + ":to:" + imOtherId;
    }

    /**
     * 获取查询时redis key
     *
     * @param param
     * @return
     */
    private String getQueryInputingRedisKey(InputingStatusParam param) {
        String imMyId = imUserIdUtils.getIMUserId(param.getMe());
        String imOtherId = imUserIdUtils.getIMUserId(param.getOther());
        return imOtherId + ":to:" + imMyId;
    }

    @Override
    public void setInputingStatus(InputingStatusParam param) {
        String inputingRedisKey = this.getSetInputingRedisKey(param);
        redisServiceUtils.setIfAbsent(inputingRedisKey, true, 5L, TimeUnit.SECONDS);
    }

    @Override
    public Boolean queryInputingStatus(InputingStatusParam param) {
        String inputingRedisKey = this.getQueryInputingRedisKey(param);
        return redisServiceUtils.exists(inputingRedisKey);
    }

    @Override
    public Integer create(CreateChatParam createChatParam) {
        Integer count = new LambdaQueryChainWrapper<>(this.baseMapper)
            .eq(ChatPO::getCallerId, createChatParam.getCustomerId())
            .eq(ChatPO::getCounselorId, createChatParam.getConsultantId())
            .isNull(ChatPO::getEndTime)
            .count();
        if (count != 0) {
            throw new RuntimeException("会话已存在");
        }
        ChatPO po = ChatPO.builder().callerId(createChatParam.getCustomerId())
            .counselorId(createChatParam.getConsultantId())
            .startTime(convert2LocalDateTime(createChatParam.getStartTime()))
            .build();
        this.save(po);
        return po.getId();
    }

    private LocalDateTime convert2LocalDateTime(long stamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(stamp), ZoneId.of("Asia/Shanghai"));
    }

    @Override
    public boolean finish(FinishChatParam finishChatParam) {
        return new LambdaUpdateChainWrapper<>(this.baseMapper)
            .eq(BasePO::getId, finishChatParam.getChatId())
            .isNull(ChatPO::getEndTime)
            .set(ChatPO::getEndTime, convert2LocalDateTime(finishChatParam.getEndTime()))
            .update();
    }

    @Override
    public boolean update(AppraiseParam param) {
        ChatPO old = new LambdaQueryChainWrapper<>(this.baseMapper)
            .eq(BasePO::getId, param.getChatId())
            .isNotNull(ChatPO::getEndTime)
            .last("limit 1")
            .one();
        if (old == null) {
            throw new IllegalArgumentException("不存在该记录");
        }
        if (param.getAppraiser() == 0) {
            if (param.getGrade() == null && StringUtils.isEmpty(param.getAppraisementFromCustomer())) {
                throw new IllegalArgumentException("评价参数错误");
            }
            if (param.getGrade() != null) {
                if (old.getScore() != null) {
                    throw new IllegalArgumentException("已评分");
                }
                old.setScore(param.getGrade());
            }
            if (StringUtils.isNotEmpty(param.getAppraisementFromCustomer())) {
                if (StringUtils.isNotEmpty(old.getCommentCaller())) {
                    throw new IllegalArgumentException("已评价");
                }
                old.setCommentCaller(param.getAppraisementFromCustomer());
            }
        } else if (param.getAppraiser() == 1) {
            if (StringUtils.isEmpty(param.getAppraisementCounselor())) {
                throw new IllegalArgumentException("评价为空");
            }
            old.setCommentCounselor(param.getAppraisementCounselor());
        } else {
            throw new IllegalArgumentException("类型错误");
        }
        baseMapper.updateById(old);
        return true;
    }

    @Override
    public List<ChatDTO> queryRecordList(ChatRecordListQueryParam queryParam) {
        return new LambdaQueryChainWrapper<>(this.baseMapper)
            .eq(ChatPO::getCallerId, queryParam.getCallerId())
            .page(new Page<>(queryParam.getStart() / queryParam.getLength() + 1, queryParam.getLength()))
            .getRecords().stream().map(ChatPO::convert2DTO).collect(Collectors.toList());
    }
}
